package luaj.utils;


import android.app.Activity;
import android.content.Context;
import android.content.Intent;

import android.ext.BaseActivity;
import android.ext.Log;
import android.graphics.Color;

import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.lang.ref.WeakReference;

import luaj.Globals;
import luaj.LuaValue;
import luaj.lib.jse.CoerceJavaToLua;
import luaj.utils.functions.print;


public class LuaActivity extends Activity {
    public static Handler handler;
    public TextView status;

    private static Globals globals;
    private ScrollView errorLayout;
    private int mWidth;
    private int mHeight;
    private String tag = "LuaActivity";
    private final static String NAME = "name";
    private final static String FILE = "file";
    private String luaDir;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        luaDir = getIntent().getStringExtra(FILE);
        handler = new MainHandler(this);

        initErrorLayout();
        initSize();
        initLua();
    }

    public static void start(Globals mglobals, File path) {
        if (!path.exists()) {
            return;
        }
        BaseActivity BASE = BaseActivity.instance;
        globals = mglobals;
        Intent starter = new Intent(BASE, LuaActivity.class);
        starter.putExtra(FILE, path.getParent());
        BASE.startActivity(starter);
    }

    public void runFunc(String funcname, Object... arg) {
        try {
            if (arg == null) {
                arg = new Object[0];
            }
            LuaValue[] value = new LuaValue[arg.length];
            LuaValue func = globals.get(funcname);
            if (func.isfunction()) {
                for (int i = 0; i < arg.length; i++) {
                    value[i] = CoerceJavaToLua.coerce(arg[i]);
                }
                func.invoke(value).arg1();
            }
        } catch (Exception e) {
            sendError("runFunc :" + e.getMessage());
        }
    }

    private void initLua() {
        try {
            globals.set("activity", CoerceJavaToLua.coerce(this));
            globals.set("this", CoerceJavaToLua.coerce(this));
            globals.set("print", new print(getGlobals()));
            globals.set("width", CoerceJavaToLua.coerce(mWidth));
            globals.set("height", CoerceJavaToLua.coerce(mHeight));
        } catch (Exception e) {
            sendMsg("init Lua :" + e.getMessage());
            Log.e("LuaActivity", e.getMessage());
        }
    }

    private void initSize() {
        WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        mWidth = outMetrics.widthPixels;
        mHeight = outMetrics.heightPixels;
    }

    private void initErrorLayout() {
        errorLayout = new ScrollView(this);
        errorLayout.setFillViewport(true);
        status = new TextView(this);
        status.setTextColor(Color.BLACK);
        status.setText("");
        status.setTextIsSelectable(true);
        errorLayout.addView(status, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
    }

    public static Globals getGlobals() {
        return globals;
    }

    public static void sendMsg(String msg) {
        seed(msg, 0);
    }

    public static void sendError(String msg) {
        seed(msg, 1);
    }

    private static void seed(String msg, int i) {
        Message message = new Message();
        Bundle bundle = new Bundle();
        bundle.putString("data", msg);
        message.setData(bundle);
        message.what = i;
        handler.sendMessage(message);
    }

    public Context getContext() {
        return this;
    }

    @Override
    protected void onStart() {
        super.onStart();
        runFunc("onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        runFunc("onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        runFunc("onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        runFunc("onStop");
    }

    @Override
    protected void onNewIntent(Intent intent) {
        runFunc("onNewIntent", intent);
        super.onNewIntent(intent);
    }

    @Override
    protected void onDestroy() {
        try {
            runFunc("onDestroy");
            System.gc();
        } catch (Exception e) {
            sendMsg("onDestroy" + e.getMessage());
            Log.e(tag, e.getMessage());
        }
        super.onDestroy();
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        runFunc("onActivityResult", requestCode, resultCode, data);
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        runFunc("onCreateOptionsMenu", menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        runFunc("onCreateContextMenu", menu, v, menuInfo);
        super.onCreateContextMenu(menu, v, menuInfo);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        runFunc("onContextItemSelected", item);
        return super.onContextItemSelected(item);
    }

    public void toast(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }


    public void newActivity(String path) throws FileNotFoundException {
        newActivity(1, path);
    }

    public void newActivity(int req, String path) throws FileNotFoundException {
        newActivity(req, path, false);
    }

    public void newActivity(int req, String path, boolean newDocument) throws FileNotFoundException {
        Intent intent = new Intent(this, LuaActivity.class);
        if (newDocument) {
            intent = new Intent(this, LuaActivityX.class);
        }
        intent.putExtra(NAME, path);
        if (path.charAt(0) != '/' && luaDir != null) {
            path = luaDir + "/" + path;
        }
        File f = new File(path);
        if (f.isDirectory() && new File(path + "/main.lua").exists()) {
            path += "/main.lua";
        }
        else if ((f.isDirectory() || !f.exists()) && !path.endsWith(".lua")) {
            path += ".lua";
        }
        if (!new File(path).exists()) {
            throw new FileNotFoundException(path);
        }
        if (newDocument) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
                intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
            }
        }
        if (newDocument) {
            startActivity(intent);
        } else {
            startActivityForResult(intent, req);
        }
    }

    private static class MainHandler extends Handler {
        WeakReference<Activity> activityWeakReference;

        private MainHandler(Activity activity) {
            activityWeakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Activity activity = activityWeakReference.get();
            if (activity == null || !(activity instanceof LuaActivity)) {
                return;
            }
            LuaActivity luaActivity = (LuaActivity) activity;
            switch (msg.what) {
                case 0: {
                    String data = msg.getData().getString("data");
                    luaActivity.toast(data);
                    luaActivity.status.append(data + "\n");
                    luaActivity.setContentView(luaActivity.errorLayout);
                    break;
                }
                case 1: {
                    String data = msg.getData().getString("data");
                    luaActivity.status.append(data + "\n");
                    luaActivity.setContentView(luaActivity.errorLayout);
                    break;
                }
            }
        }
    }
}
